你大概寫過這樣的程式碼。一個 viewModelScope.launch 包住一段網路請求,一個 async 搭配 awaitAll 平行抓了好幾筆資料,跑起來一切正常,畫面該更新的時候更新,該轉圈圈的時候轉圈圈。你把這段程式碼複製貼上到下一個專案,改幾個變數名稱,一樣能動。久而久之你也習慣了這種寫法,覺得自己已經會用協程了。
真正的裂縫,通常出現在一次意外的 debug 現場。可能是某個協程明明呼叫了取消,畫面卻還是在跑;可能是某個 try-catch 包住了整個 launch,例外卻像穿牆一樣直接讓 App 當掉;也可能只是主管隨口問了一句,這個 suspend function 執行到一半跑去哪裡了,你張口卻答不出來。你開始意識到,自己會的其實是「照著範例改寫」,而不是「理解協程在做什麼」。這兩件事表面上看起來很像,實際上是完全不同量級的能力,前者讓程式碼能動,後者讓你在程式碼出問題的當下,知道問題可能出在哪裡。
這正是想要撰寫這個系列的理由。
這個系列不是一份 Kotlin 協程 API 的中文翻譯導讀,市面上這類文件不缺,缺的是把這些 API 串起來的那條時間軸。核心目標只有一個,讓你看到一段協程程式碼時,能在腦中還原出它的執行順序,知道它何時暫停、何時恢復、暫停時這個協程的狀態被誰持有、又是在什麼條件下會被取消。具備這種能力之後,launch 與 async 不再是兩個要背起來的關鍵字,而是你能推導出彼此差異的兩種行為模式。
目標讀者是已經在專案裡用過協程,但沒有系統化的學過它底層在做什麼的工程師。你可能是 Android 工程師,也可能是用 Ktor 寫後端服務,或是嘗試 Kotlin Multiplatform,KMP,跨平台開發,甚至只是單純想把 Kotlin 當成主力語言深耕。這個系列不預設你正在用哪一種應用框架,唯一的門檻是你看得懂 Lambda、擴充函式、高階函式這些 Kotlin 基礎語法。如果你完全沒寫過 Kotlin,這個系列會有點吃力,建議先把語法基礎打穩再回來。
這裡要特別說明一件事避免讀者混淆。另一個系列「Spring Boot 3 + Kotlin 協程高併發,後端開發新選擇」也會談協程,但那個系列的立場是拿協程去解決 Spring Boot 後端在高併發場景下的實務問題,情境綁定在訂單查詢與扣庫存這類後端服務上。這個系列完全不同,聚焦的是協程這套語言機制本身,不綁任何後端框架,也不預設你在寫後端。如果你是 Android 工程師或 KMP 開發者,那個系列對你幫助有限,這個系列才是你該從頭讀起的起點。反過來說,如果你已經是 Spring Boot 後端工程師,把這個系列當成地基,再去讀那個系列會走得更穩,因為那個系列會直接假設你已經具備這裡建立的心智模型。
這個系列採「暫停的秘密 > 結構化並發地基 > 執行環境與例外治理 > Flow 資料流 > 測試與實戰整合」的五段式弧線,前兩階段刻意放慢腳步,用 11 天把 suspend function 的底層原理與結構化並發的規則打穩。市面上不少協程教學急著在第三、四天就跳進 Flow,讀者往往似懂非懂地硬套用法,卻答不出來 Flow 底下的協程到底何時被取消。這個系列反其道而行,先把地基做扎實,後面的內容才站得住腳。
全系列共用一條輕量、跨平台皆適用的示範情境,一個多來源圖片下載與聚合工具。第一天它只是一個會卡住主執行緒的單一下載函式,簡陋到幾乎不值得稱作工具。隨著系列推進,結構化並發、取消機制、例外處理這些觀念陸續建立起來,它會陸續長出多來源平行下載、逾時控制、失敗重試這些真實情境會遇到的複雜度,到了 Flow 階段,它會收斂成一個能持續回報下載進度的資料流。到系列後段,這個工具會有一個正式的名字,圖片下載工具完整版,並在測試與實戰整合期補齊單元測試,附上簡短的跨平台示範,看看同一套協程邏輯在 Android 與 Ktor 上分別怎麼用。
你不需要每天都回頭補完整個專案,每天用到的只是整體工具的一個切片,讀完當天內容不會卡關。但如果你跟著系列一路讀下來,會明顯感覺到這個工具的異步控制能力一天比一天完整,這種累積感,正是我們刻意設計的,因為協程的價值往往要在情境變複雜之後才真正顯現出來,一個永遠只下載一張圖片的範例,是看不出結構化並發為什麼重要的。
以下依五個階段分組呈現整個系列的全貌。每個階段標題下方先說明這個階段要讓你建立起什麼樣的能力,再列出該階段每一天的標題與一句話定位。閱讀當下不需要理解每一天的技術細節,只需要對整體節奏有個印象,等你實際走到某一天,回來這裡對照一下自己的位置即可。
五天,目標是建立協程存在的動機,拆解 suspend function 與 Continuation 的底層機制,學會三種 Coroutine Builder 的差異與選用時機。
六天,目標是建立 Coroutine Scope、Structured Concurrency、Job、取消機制這幾個貫穿全系列的核心心智模型。
七天,目標是掌握協程實際跑在哪、上下文如何組成、例外如何傳播與隔離,建立生產等級的錯誤處理習慣。
七天,目標是理解 Flow 為何存在、如何操作與組合,並掌握 StateFlow、SharedFlow、Channel、背壓這些進階資料流控制手段。
五天,目標是學會用官方測試框架驗證協程行為,盤點常見陷阱與最佳實踐,收斂進一個具名示範專案並完賽總結。
30 天的天數配置刻意不均分,這是一套有意識設計的難度曲線。前兩階段用 11 天把暫停機制與結構化並發的地基打穩,看起來進度慢,實際上是為了避免你在還不理解 Structured Concurrency 之前就被丟進 Flow、Channel 這些建立在協程之上的進階抽象,導致似懂非懂地硬套用法,遇到問題時卻找不到根源。執行環境與例外治理階段給了七天,是因為 Dispatchers、Context、例外傳播這些內容一旦沒學紮實,會直接反映在正式環境的錯誤處理品質上。
回到文章開頭那個讓你答不出來的瞬間,某個協程明明取消了卻還在跑,某個例外像穿牆一樣繞過了你的 try-catch。這些現象不是巧合,也不是協程設計得不好,而是背後有一套明確的規則在運作,只是你還沒看過那條時間軸。這 30 天要做的,就是把這條時間軸攤開來給你看清楚,讓你下次遇到類似狀況時,能靠推理而不是靠猜測找到問題所在。
明天我們將正式進入 《Day 01:為什麼你需要協程,從一個會卡住主執行緒的下載函式說起》,從那個會卡住主執行緒的下載函式開始,把協程存在的理由攤開來看清楚。